﻿//----------------------------------------------------------------
//CodeArt.
//
//文件描述:
//
//创 建 人: dreamnan@hotmail.com(Blog:http://www.cnblogs.com/dreamnan)
//创建日期: 2010-6-15
//
//修订记录: 
// 2011-1209 SelectedFields改成保存InternalName
//          默认查询当前视图的字段    
//          最后一行不满时，按钮不放到新行中  
//          修改样式，满足正常moss显示。
//          可以从列表的所有字段中选择要查询的字段
//          资源文件放到12/Resources中,默认资源文件改成英文。     
//          基类改成BaseSPWebPart，可能造成跟以前wp不兼容，需要删除旧wp，重新添加
//----------------------------------------------------------------

using System;
using System.Collections.Generic;

using System.ComponentModel;
using System.Reflection;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Xml.Serialization;
using System.Collections;
using System.Configuration;
using System.IO;
using System.Data;
using System.Text;

namespace CodeArt.SharePoint.SmartQuery
{
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Utilities;
    using Microsoft.SharePoint.WebControls;
    using Microsoft.SharePoint.WebPartPages;

    using CodeArt.SharePoint.CamlQuery;
    using CodeArt.SharePoint.SmartQuery;
using System.Web.UI.WebControls.WebParts;
    using Microsoft.SharePoint.Administration;

    [DefaultProperty("Text"), ToolboxData("<{0}:ListQueryWebPart runat=server></{0}:ListQueryWebPart>"), XmlRoot(Namespace = "CodeArt.SharePoint.SmartQuery")]
    public class ListQueryWebPart : BaseSPWebPart, ICamlProvider
    {
        #region Variable

        //private string defaultTitle;
        private bool redrawingSuspended;
        private int columnsNum = 4;
        private string _selectedFields;
        private Table tbSimpleSearch = new Table();
        //private Table tbComplexSearch = new Table();
        private Table tbButtonSearch = new Table();
        private Button btnSearches = new Button();
        //private Coolite.Ext.Web.ScriptManager sm = new Coolite.Ext.Web.ScriptManager();

        internal static char[] s_CommaSeparator = new char[] { ';' };

        internal static List<string> ExcludedFields =
            new List<string> { "DocIcon", "LinkTitle", "LinkTitle2", "LinkTitleNoMenu", "LinkFilenameNoMenu", "LinkFilename", "LinkFilename2",
            "ItemChildCount","FolderChildCount", "Edit"};

        #endregion

        #region construct

        /// <summary>
        /// 构造函数
        /// </summary>
        public ListQueryWebPart()
        {
            //base.Init += new EventHandler(this.SearchesList_Init);
        }

        #endregion

        #region Properties

        //public new SPSite Site
        //{
        //    get { return this.ItemContext.Site; }
        //}

        public SPWeb Web
        {
            get { return this.ItemContext.Web; }
        }

        public SPList List
        {
            get { return this.ItemContext.List;}
        }

        public virtual SPContext ItemContext
        {
            get
            {
                SPContext itemContext = null;

                HttpContext context = HttpContext.Current;
                if (context != null)
                {
                    itemContext = SPContext.GetContext(context);
                }

                return itemContext;
            }
        }
        
        /// <summary>
        /// 最多显示条目
        /// </summary>
        [WebPartStorage(Storage.Shared),
        //FriendlyName("显示列数"),
        //Description("输入查询面板的列数，默认为4列。"),
        WebBrowsable(false),
        DefaultValue(4)]
        public int ColumnsNum
        {
            get
            {
                return this.columnsNum;
            }
            set
            {
                this.columnsNum = value;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [WebPartStorage(Storage.Personal),
        FriendlyName("选中Field的InternalName字符串"),
        Description("格式为Title|Create|Modified"),
        Browsable(true),
        DefaultValue("")]
        public string SelectedFields
        {
            get
            {
                return this._selectedFields;
            }
            set
            {
                this._selectedFields = value;
            }
        }

        #endregion

        internal string GetDefaultSelectedFields()
        {
            string strFields = "";
            if (SPContext.Current.ViewContext != null && SPContext.Current.ViewContext.View != null)
            {
                var fields = SPContext.Current.ViewContext.View.ViewFields.ToStringCollection();
                if(fields.Contains("LinkTitle"))
                {
                    fields.Insert(fields.IndexOf("LinkTitle"),"Title");
                    fields.Remove("LinkTitle");
                }
                foreach (string f in fields)
                {
                    if (ExcludedFields.Contains(f))
                        continue;

                    if (f == "Attachments") //默认不查询是否有附件
                        continue;

                    var field = this.List.Fields.GetField(f);
                    if (field is SPFieldWorkflowStatus)
                        continue;

                    if (strFields != "")
                        strFields += s_CommaSeparator[0];

                    if (f == "LinkTitle")
                        strFields += "Title";
                    else
                        strFields += f;
                }
            }
            return strFields;
        }

        #region Override Method

        ///// <summary>
        ///// 创建子控件
        ///// </summary>
        protected override void CreateChildControls()
        {
            if (this.ChildControlsCreated) return;

            this.Controls.Clear();
            //Coolite.Ext.Web.ScriptManager sm = new Coolite.Ext.Web.ScriptManager();
            //this.Controls.Add(sm);
            try
            {
                //base.UseDefaultStyles = false;

                if (String.IsNullOrEmpty(this.SelectedFields))
                    this.SelectedFields = GetDefaultSelectedFields();
              
                if (!string.IsNullOrEmpty(this.SelectedFields))
                {
                    this.Controls.Add(this.tbSimpleSearch);
                    tbSimpleSearch.ID = "tbSimpleSearch";
                    //tbSimpleSearch.Attributes["runat"] = "server";
                    tbSimpleSearch.Attributes.Add("class", "ms-formtable");//ms-formtable");
                    
                    //tbSimpleSearch.Attributes.Add("width", "100%");
                    
                    tbSimpleSearch.Attributes.Add("cellpadding", "2");
                    tbSimpleSearch.Attributes.Add("cellspacing", "2");
                    tbSimpleSearch.Attributes.Add("border", "0");
                    //tbSimpleSearch.Attributes.Add("style", "padding-left:10px;padding-top:10px");
                    this.Controls.Add(this.tbSimpleSearch);

                    tbSimpleSearch.Controls.Clear();

                    string[] fields = this.SelectedFields.Split(s_CommaSeparator);
                    TableRow fieldSimpleTr = new TableRow();
                    int colIndex = 0;
                    foreach (string field in fields)
                    {
                        fieldSimpleTr.Controls.Add(CreateSimpleLabel(field));
                        fieldSimpleTr.Controls.Add(CreateSimpleField(field));
                        colIndex ++;

                        if (colIndex == this.ColumnsNum)
                        {
                            colIndex = 0;
                            this.tbSimpleSearch.Rows.Add(fieldSimpleTr);
                            
                            //TableRow row1 = new TableRow();
                            //TableCell cell1 = new TableCell();
                            //cell1.Attributes.Add("colspan", Convert.ToString(this.ColumnsNum*2));
                            //cell1.Controls.Add(new ToolPartItemSeparator());
                            //row1.Cells.Add(cell1);
                            //this.tbSimpleSearch.Controls.Add(row1);
                            
                            fieldSimpleTr = new TableRow();
                        }
                    }
                    this.tbSimpleSearch.Rows.Add(fieldSimpleTr);

                    var maxColCount = this.ColumnsNum * 2;
                    var btnCell = CreateSearchButton();
                    if (fieldSimpleTr.Cells.Count < maxColCount) //by zjy, 2011-12, 充分利用最后一行
                    {
                        var span = maxColCount - fieldSimpleTr.Cells.Count;
                        for (int i = 1; i < span; i++)
                        {
                            fieldSimpleTr.Cells.Add(new TableCell());
                        }
                        btnCell.ColumnSpan = 1;
                        btnCell.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Left;
                        fieldSimpleTr.Cells.Add(btnCell);
                    }
                    else
                    {
                        TableRow buttonRow = new TableRow();
                        buttonRow.Controls.Add(btnCell);
                        this.tbSimpleSearch.Rows.Add(buttonRow);
                    }                  
                }
                // this.btnSearches.Click += new EventHandler(btnSearches_Click);               
                this.ChildControlsCreated = true;

                //保证2010下，控件能显示出边框
                if(SPFarm.Local.BuildVersion.Major>12)
                    CssRegistration.Register("forms.css"); //add by zjy , 2007下会出错

            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            this.EnsureChildControls();
        }
            
        #region ICamlProvider 成员

        private CamlExpression _Expression;

        public virtual CamlExpression QueryExpression
        {
            get
            {
                if (_Expression != null)
                    return _Expression;

                foreach (TableRow row in tbSimpleSearch.Rows)
                {
                    foreach (TableCell cell in row.Cells)
                    {
                        if (cell.Controls.Count == 0)
                            continue;
                        Control ctl = cell.Controls[0];
                        if (ctl is ICamlProvider)
                        {
                            ICamlProvider p = (ICamlProvider)ctl;

                            CamlExpression tempExpr = p.QueryExpression;

                            if (tempExpr != null)
                            {
                                if (_Expression == null)
                                    _Expression = p.QueryExpression;
                                else
                                    _Expression = _Expression && p.QueryExpression;
                            }
                        }
                    }
                }

                return _Expression;

            }
        }

        #endregion

        public override EditorPartCollection CreateEditorParts()
        {
            var editors = base.CreateEditorParts();

            EditorPart[] newEditors = new EditorPart[1];
            newEditors[0] = new ListQueryToolPart(this);
            newEditors[0].ID = "ListQueryToolPart";

            return new EditorPartCollection(editors, newEditors);
        }

        /// <summary>
        /// 工具箱设定
        /// </summary>
        /// <returns></returns>
        //public override ToolPart[] GetToolParts()
        //{
        //    ToolPart[] partArray2 = new ToolPart[2];
        //    WebPartToolPart part1 = new WebPartToolPart();
        //    //part1.Hide(WebPartToolPart.Properties.DetailLink);
        //    //part1.Hide(WebPartToolPart.Properties.Title);
        //    partArray2[1] = part1;
        //    try
        //    {
        //        ListQueryToolPart part0 = new ListQueryToolPart(this);
        //        part0.ID = "ListQueryToolPart";
        //        partArray2[0] = part0;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //    return partArray2;
        //}

        #endregion

        /// <summary>
        /// 延缓重画
        /// </summary>
        public void SuspendRedraw()
        {
            this.redrawingSuspended = true;
        }

        /// <summary>
        /// 重启重画
        /// </summary>
        public void ResumeRedraw()
        {
            this.redrawingSuspended = false;
            this.DoRedraw();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (!Page.IsPostBack)
                return;

            if (this.QueryExpression == null)
                return;

            string qxml = CamlBuilder.Where(this.List, this.QueryExpression);
            this.SetCurrentListViewSchemaQuery(qxml);
        }

        #region private method
        CamlExpression AppendExpression(CamlExpression expr1, CamlExpression expr2)
        {
            if (expr1 == null)
                return expr2;
            else
                return expr1 && expr2;
        }

        /// <summary>
        /// 改变当前列表的查询过滤条件
        /// </summary>
        /// <param name="qxml"></param>
        private void SetCurrentListViewSchemaQuery(string qxml)
        {
            if (String.IsNullOrEmpty(qxml)) return;
            ListWebPartQueryManager.ChangeWebPartsQuery(this.List, this.Zone.WebParts, qxml);       
        }

        /// <summary>
        /// 修改视图中的查询条件部分
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="query"></param>
        //void ChangeSchemaXmlQuery(XmlDocument doc, string query)
        //{
        //    if (String.IsNullOrEmpty(query)) return;

        //    string innerQuery = GetInnerQuery(query);
        //    if (innerQuery == "") return;

        //    XmlNode queryNode = doc.DocumentElement.SelectSingleNode("Query");
        //    //queryNode.InnerXml = qxml;

        //    XmlNode whereNode = queryNode.SelectSingleNode("Where");

        //    string viewXml = string.Empty;

        //    if (whereNode != null)
        //    {
        //        queryNode.RemoveChild(whereNode);
        //        viewXml = whereNode.InnerXml;
        //    }

        //    XmlNode newWhereNode = doc.CreateElement("Where");

        //    string qryxml = string.Empty;

        //    if (!string.IsNullOrEmpty(viewXml))
        //    {
        //        qryxml = string.Format("<And>{0}{1}</And>", viewXml, innerQuery);
        //    }
        //    else
        //    {
        //        qryxml = innerQuery;
        //    }
        //    newWhereNode.InnerXml = qryxml;

        //    queryNode.AppendChild(newWhereNode);

        //    XmlNode ViewEmptyNode = doc.DocumentElement.SelectSingleNode("ViewEmpty");

        //    ViewEmptyNode.InnerXml = "<HTML><![CDATA[<font color='red'>" +
        //        ResourcesHelper.GetResourceString("NoFoundItems", "未找到符合查询条件的记录。") + "</font>]]></HTML>";

        //}

        //string GetInnerQuery(string q)
        //{
        //    XmlDocument doc = new XmlDocument();
        //    doc.LoadXml(q);

        //    return doc.DocumentElement.InnerXml;
        //}

  
        private void DoRedraw()
        {
            if (!this.redrawingSuspended)
            {
                base.ChildControlsCreated = false;
                this.EnsureChildControls();
            }
        }

        private TableCell CreateSimpleLabel(string field)
        {
            var f = this.List.Fields.GetField(field);

            TableCell tcTemp = new TableCell();
            tcTemp.VerticalAlign = VerticalAlign.Middle;
            tcTemp.HorizontalAlign = HorizontalAlign.Left;
            int intPercentage = 100 / this.ColumnsNum;
            //tcTemp.Attributes.Add("style", "width: " + intPercentage.ToString() + "%; ");
            //tcTemp.Attributes.Add("class", "ms-formlabel");
            tcTemp.Wrap = false;
            tcTemp.Controls.Add(new LiteralControl(f.Title + ": "));

            return tcTemp;
        }

        private TableCell CreateSimpleField(string field)
        {
            TableCell tcTemp = new TableCell();
            tcTemp.VerticalAlign = VerticalAlign.Middle;
            tcTemp.HorizontalAlign = HorizontalAlign.Left;
            int intPercentage = 80 / this.ColumnsNum;
            tcTemp.Attributes.Add("style", "width: " + intPercentage.ToString() + "%; ");
            //tcTemp.Attributes.Add("class", "ms-formbody");
            tcTemp.Attributes.Add("nowrap","true");
            
            QueryControl ctlField = new QueryControl();
            ctlField.ID = "ft_" + field;
            ctlField.FieldName = field;
            ctlField.ShowTitle = false;
            //ctlField.Attributes.Add("style", "width:90%");
            tcTemp.Controls.Add(ctlField);  

            return tcTemp;
        }

        private TableCell CreateSearchButton()
        {
            TableCell tcTemp = new TableCell();
            tcTemp.VerticalAlign = VerticalAlign.Bottom;
            tcTemp.HorizontalAlign = HorizontalAlign.Right;
            tcTemp.ColumnSpan = this.ColumnsNum*2;
            //tcTemp.Attributes.Add("style", "width:99%");
            this.btnSearches.ID = "btnSearches";
            //this.btnSearches.Attributes.Add("class", "ms-ButtonHeightWidth");
            this.btnSearches.Text = " "+ResourcesHelper.GetResourceString("Search", "查询") + " ";
            tcTemp.Controls.Add(this.btnSearches);

            return tcTemp;
        }

        #endregion 
    }

}
